﻿using System.Collections.Generic;
using System.Linq;
using Fujitsu.JiraAnalysis.TrackingSystemAdapter;
using Fujitsu.JiraAnalysis.DAL;
using System.Data.Objects.DataClasses;
using Fujitsu.JiraAnalysis.ReplicationService.SynchronizeExceptions;
using Fujitsu.JiraAnalysis.JiraRPC;

namespace Fujitsu.JiraAnalysis.ReplicationService.Synchronize
{
    public interface ISyncBase
    {
        void StartSync(ITrackSystemInfo adapter, Project project);
    }
    public abstract class SyncBase<T, TV> : ISyncBase
        where T : AbstractNamedRemoteEntity
        where TV : EntityObject
    {
        private int ProjectId { get; set; }

        public void StartSync(ITrackSystemInfo adapter, Project project)
        {
            ProjectId = project.ID;
            var trackSystemInfoItems = GetTrackSystemInfoItems(project, adapter);
            var storageItems = GetStorageItems(ProjectId);

            if (trackSystemInfoItems.Count() > storageItems.Count)
            {
                throw GetSyncException(project.Name, ProjectId, project.ProjectKey);
            }

            foreach (var trackSystemInfoItem in trackSystemInfoItems)
            {
                var match = FindMatchInStorage(storageItems, trackSystemInfoItem, ProjectId);
                if (match == null)
                    throw GetSyncException(project.Name, ProjectId, project.ProjectKey);
                Update(trackSystemInfoItem, match);
            }
        }

        protected abstract SyncException GetSyncException(string projectName, int projectId, string projectKey);

        protected abstract List<TV> GetStorageItems(int projectId);

        protected abstract List<T> GetTrackSystemInfoItems(Project project, ITrackSystemInfo adapter);

        protected abstract TV FindMatchInStorage(List<TV> storageItems, T trackSystemInfoItem, int projectId);

        protected abstract void Update(T trackSystemItem, TV entityObject);
    }
}
